# -*- coding: utf-8 -*-

# -------------------------------
# Author    : linlingwei
# Email     : 951035650@qq.com
# File Name : bodyTemplate.py
# Date      : 2018/11/7
# IDE       : PyCharm
# Version   : 1.0.1
# -------------------------------


__author__ = "lin lingwei"
import json

import configs.constants.suffix_constant as sc
import configs.constants.nodeType_constant as nc
import configs.constants.body_constant as bc
import configs.constants.attribute_constant as ac

import maya.cmds as mc

import scripts.commonCmds as con
import scripts.curveCmds as crc
reload(con)

__version__ = "3.2.5"

gbCtr = "_".join([bc.gBodyTemplate,sc.sCtr])

armDict = {bc.gShoulder:[0,0,0],
           bc.gArm:[2,0,0],
           bc.gForeArm:[5,0,-1],
           bc.gWrist:[8,0,0],
           bc.gHand:[10,0,0],
           bc.gHandEnd:[12,0,0],
           bc.gPolar:[5,0,-6]
           }

legDict = {bc.gThigh:[2,8,0],
           bc.gLeg:[2,7,0],
           bc.gShank:[2,4,1],
           bc.gAnkle:[2,1,0],
           bc.gToeA:[2,0,1],
           bc.gToe:[2,0,2],
           bc.gToeTip:[2,0,3],

           bc.gPolar:[2,4,5],
           bc.gHeel:[2,0,-1],
           bc.gFootInside:[1,0,2],
           bc.gFootOutside:[3,0,2]
           }
spineDict = {bc.gSpine:[0,7,0],
             bc.gChest:[0,18,0]}
neckDict = {bc.gNeck:[0,19,0],
             bc.gHead:[0,21,0]}
def init():
    if not mc.objExists(bc.gBodyTemplate):
        gb = mc.createNode(nc.tTransform,name = bc.gBodyTemplate)
        mc.addAttr(gb, ln="version", at="enum", en="{}:".format(__version__), k=True, )
        mc.addAttr(gb, ln="author", at="enum", en="{}:".format(__author__), k=True, )

        mc.setAttr(gb + ".version", l=True)
        mc.setAttr(gb + ".author", l=True)
        con.lockHideAttr(gb, ignore=["v"])
        mc.lockNode(gb, lock=True)

        crc.createControl(gbCtr, colorId=18)
        mc.parent(gbCtr,bc.gBodyTemplate)
        crc.scaleXYZ(gbCtr, 8)
        con.emptyGroup(gbCtr)
        mc.addAttr(gbCtr, ln=ac.global_scale, at="float", dv=1, min=0.01, k=True)
        for attr in ['sx', 'sy', 'sz']:
            mc.connectAttr("{}.{}".format(gbCtr, ac.global_scale), "{}.{}".format(gbCtr, attr))
            
        con.lockHideAttr(gbCtr, ['tx', "rx", "rz", "sx", "sy", "sz", "v"])
        
    if not mc.objExists(bc.gBodyTemplateSet):
        
        mc.sets(name = bc.gBodyTemplateSet,em=True)
    return

def localInit(tag,prefix="def"):
    
    # -----
    init()
    # -----
    
    localGrp = con.lname(prefix,tag,bc.gTemplate,sc.sGrp)
    if not mc.objExists(localGrp):
        mc.createNode(nc.tTransform,name = localGrp,parent= gbCtr)
        
    localSet = con.lname(tag,bc.gTemplate,bc.sSet)
    if not mc.objExists(localSet):
        mc.sets(name= localSet,em=True)
        mc.sets(localSet,add=bc.gBodyTemplateSet)
        
    localPrefix = con.lname(prefix,tag,bc.gTemplate,bc.sSet)
    if not mc.objExists(localPrefix):
        mc.sets(name= localPrefix,em=True)
        mc.sets(localPrefix,add=localSet)
    return localGrp,localPrefix

def tempLoc(name,position=(0,0,0),tag=None):
    mc.select(cl=True)
    tmpJot = mc.joint(name="_".join([name,bc.gTemplate]),p=position,rad=1)
    locShape = mc.createNode(nc.tLocator,name="_".join([name,bc.gTemplate+sc.sLoc]),parent=tmpJot)
    con.changColor(tmpJot, 18)
    
    mc.addAttr(tmpJot,ln="localScale",at="float",dv=1,k=True)
    mc.connectAttr(tmpJot+".localScale",locShape+".localScaleX")
    mc.connectAttr(tmpJot+".localScale",locShape+".localScaleY")
    mc.connectAttr(tmpJot+".localScale",locShape+".localScaleZ")
    
    if tag:
        mc.setAttr(tmpJot+".type",18)
        mc.setAttr(tmpJot+".otherType",tag,type="string")
    return tmpJot

def importArmTemplate(prefix="def",shoulder=True):
    localGrp,localSet = localInit(bc.gArm,prefix)
    if shoulder:
        relate = [bc.gShoulder,bc.gArm,bc.gForeArm,bc.gWrist,bc.gHand,bc.gHandEnd]
    else:
        relate = [bc.gArm,bc.gForeArm,bc.gWrist,bc.gHand,bc.gHandEnd]

    pat = None
    newDict = {sc.sGrp:localGrp,"make":prefix}
    tloclist = list()
    for rel in relate:
        tloc = tempLoc("_".join([prefix,rel]),armDict[rel],rel)
        tGrp = con.emptyGroup(tloc, ["Zero"])
        if pat is not None:
            mc.parent(tGrp[0],pat)
        else:
            mc.parent(tGrp[0],localGrp)
        pat = tloc
        newDict[rel] = tloc
        mc.sets(tloc,add=localSet)
        con.lockHideAttr(tloc, ["sx", "sy", "sz", "v"])
        tloclist.append(tloc)
    # mc.joint(tloclist, e=True, oj='yzx', secondaryAxisOrient='zup', ch=True, zso=True)
    con.jointOrient(tloclist)
    ploc = tempLoc("_".join([prefix,"arm",bc.gPolar]),armDict[bc.gPolar],bc.gPolar)
    newDict[bc.gForeArmPolar] = ploc
    
    mc.sets(ploc, add=localSet)
    
    pGrp = con.emptyGroup(ploc, ["Zero", "Con"])
    mc.parent(pGrp[0], localGrp)

    # mc.parent(ploc,newArmDict[gForeArm])
    con.createAnn(newDict[bc.gForeArm], ploc + sc.sLoc)
    mc.parentConstraint(newDict[bc.gForeArm],pGrp[1],mo=True)
    mc.setAttr(localGrp+".tx",2)
    mc.setAttr(localGrp+".ty",18)
    
    con.lockHideAttr(newDict[bc.gForeArm], ["ty", "rx", "rz"])
    con.lockHideAttr(newDict[bc.gWrist], ["ty"])
    con.lockHideAttr(newDict[bc.gHandEnd], ["ty", "tz", "rx", "ry", "rz"])
    con.lockHideAttr(ploc, ["ty", "tx", "rx", "ry", "rz", "sx", "sy", "sz", "v"])
    
    data = json.dumps(newDict)
    
    con.addStringAttr(localSet, "crvData", data)
    
    return newDict
def importLegTemplate(prefix="def",thigh = True):
    localGrp, localSet = localInit(bc.gLeg, prefix)
    
    
    if thigh:
        relate = [bc.gThigh, bc.gLeg, bc.gShank, bc.gAnkle,bc.gToeA, bc.gToe, bc.gToeTip]
    else:
        relate = [ bc.gLeg, bc.gShank, bc.gAnkle,bc.gToeA, bc.gToe, bc.gToeTip]

    # relate = [gThigh, gLeg, gShank, gAnkle, gToe, gToeTip]
    pat = None
    newDict = {sc.sGrp:localGrp,"make":prefix}
    
    tloclist = list()

    for rel in relate:
        tloc = tempLoc("_".join([prefix, rel]), legDict[rel],rel)
        tGrp = con.emptyGroup(tloc, ["Zero"])
        if pat is not None:
            mc.parent(tGrp[0], pat)
        else:
            mc.parent(tGrp[0], localGrp)
        pat = tloc
        newDict[rel] = tloc
        mc.sets(tloc, add=localSet)
        con.lockHideAttr(tloc, ["sx", "sy", "sz", "v"])
        tloclist.append(tloc)
        
    # mc.joint(tloclist, e=True, oj='yzx', secondaryAxisOrient='zup', ch=True, zso=True)
    con.jointOrient(tloclist)

    extra = [bc.gPolar, bc.gHeel, bc.gFootInside, bc.gFootOutside]
    for el in extra:
        tloc = tempLoc("_".join([prefix, el]), legDict[el],el)
        newDict[el] = tloc
        mc.sets(tloc, add=localSet)
        con.lockHideAttr(tloc, ["sx", "sy", "sz", "v"])
        
    pGrp = con.emptyGroup(newDict[bc.gPolar], ["Zero", "Con"])
    mc.parent(pGrp[0], localGrp)
    con.createAnn(newDict[bc.gShank], newDict[bc.gPolar] + sc.sLoc)
    mc.parentConstraint(newDict[bc.gShank],pGrp[1],mo=True)
    
    pGrp = con.emptyGroup(newDict[bc.gHeel], ["Zero", "Con"])
    mc.parent(pGrp[0], localGrp)
    con.createAnn(newDict[bc.gAnkle], newDict[bc.gHeel] + sc.sLoc)
    mc.parentConstraint(newDict[bc.gAnkle],pGrp[1],mo=True)
    
    pGrp = con.emptyGroup(newDict[bc.gFootInside], ["Zero", "Con"])
    mc.parent(pGrp[0], localGrp)
    con.createAnn(newDict[bc.gToe], newDict[bc.gFootInside] + sc.sLoc)
    mc.parentConstraint(newDict[bc.gToe],pGrp[1],mo=True)
    
    pGrp = con.emptyGroup(newDict[bc.gFootOutside], ["Zero", "Con"])
    mc.parent(pGrp[0], localGrp)
    con.createAnn(newDict[bc.gToe], newDict[bc.gFootOutside] + sc.sLoc)
    mc.parentConstraint(newDict[bc.gToe],pGrp[1],mo=True)


    con.lockHideAttr(newDict[bc.gShank], ["tx", "ry", "rz"])
    con.lockHideAttr(newDict[bc.gPolar], ["ty", "tx", "rx", "ry", "rz", "sx", "sy", "sz", "v"])

    con.lockHideAttr(newDict[bc.gFootOutside], ["rx", "ry", "rz"])
    con.lockHideAttr(newDict[bc.gFootInside], ["rx", "ry", "rz"])
    con.lockHideAttr(newDict[bc.gHeel], ["rx", "ry", "rz"])

    data = json.dumps(newDict)
    con.addStringAttr(localSet, "crvData", data)
    
    return newDict

def importSpineTemplate(prefix="def",tag=bc.gSpine):
    
    localGrp, localSet = localInit(tag, prefix)
    if tag == bc.gSpine:
        relate = [bc.gSpine, bc.gChest]
        localDict = spineDict
    elif tag == bc.gNeck:
        relate = [bc.gNeck, bc.gHead]
        localDict = neckDict
    pat = None
    newDict = {sc.sGrp:localGrp,"make":prefix}
    for rel in relate:
        tloc = tempLoc("_".join([prefix, rel]), localDict[rel])
        tGrp = con.emptyGroup(tloc, ["Zero"])
        if pat is not None:
            mc.parent(tGrp[0], pat)
        else:
            mc.parent(tGrp[0], localGrp)
        pat = tloc
        newDict[rel] = tloc
        mc.sets(tloc, add=localSet)
        con.lockHideAttr(tloc, ["sx", "sy", "sz", "v"])
        
    ptlist = [localDict[rel] for rel in relate]
    cvnum = len(ptlist)
    if cvnum > 2 :
        deg = 2
    else:
        deg = 1
            
    crv = mc.curve(name=con.lname(prefix, tag, sc.sCrv + bc.gTemplate),
                   p=ptlist, d = deg)
    
    crvShape = con.findRelatedShape(crv)
    for i,k in enumerate(relate):
        tshape = con.findRelatedShape(newDict[k])
        mc.connectAttr(tshape+".wp[0]",crvShape+".cp[%s]"%i)
    
    newDict[sc.sCrv] = crv
    newDict["deltmp"] = []
    data = json.dumps(newDict)
    con.addStringAttr(localSet, "crvData", data)
    
    mc.parent(crv,bc.gBodyTemplate)
    
    return newDict

def refreshShineTemplate(prefix="def",number=5,tag=bc.gSpine):
    localPrefix = con.lname(prefix,tag,bc.gTemplate,bc.sSet)

    data = mc.getAttr(localPrefix + ".crvData")
    
    sdict = json.loads(data)
    if tag == bc.gSpine:
        star = bc.gSpine
        end = bc.gChest
    elif tag == bc.gNeck:
        star = bc.gNeck
        end = bc.gHead
    
    mc.parent(sdict[end],w=True)
    
    tmpCrv = con.findRelatedShape(sdict[sc.sCrv])
    span = mc.getAttr(tmpCrv+".spans")
    mc.rebuildCurve(sdict[sc.sCrv],s=span,d=2,tol=0.01)
    pro = 1.0/(number-1)
    
    newDict = {sc.sGrp:sdict[sc.sGrp],"make":prefix}
    pat = sdict[star]
    
    if sdict["deltmp"]:
        mc.parent(sdict["deltmp"],w=True)
        mc.delete(sdict["deltmp"])
    
    relate = [star]
    deltmp = []
    tjotlist = list()
    for num in range(number)[1:-1]:
        poci = mc.createNode(nc.tPointOnCurveInfo,name="temp%s"%num)
        mc.connectAttr(tmpCrv+".worldSpace[0]",poci+".ic")
        mc.setAttr(poci+".top",1)
        mc.setAttr(poci+".pr",pro*num)
        
        pt = mc.getAttr(poci+".p")[0]
        lname = star+str(num)
        
        tloc = tempLoc(name="_".join([prefix, lname]),position=pt)
        # tGrp = con.emptyGroup(tloc, ["Zero"])

        mc.parent(tloc,pat)
        pat = tloc
        newDict[lname] = tloc
        mc.sets(tloc, add=localPrefix)
        con.lockHideAttr(tloc, ["sx", "sy", "sz", "v"])
        
        relate.append(lname)
        deltmp.append(tloc)
        tjotlist.append(tloc)
    if number > 2:
        mc.parent(sdict[end],tloc)
    else:
        mc.parent(sdict[end],sdict[star])
    mc.setAttr(sdict[end]+".r",0,0,0)
    newDict[star] = sdict[star]
    newDict[end] = sdict[end]
    newDict["deltmp"] = deltmp
    relate.append(end)
    
    newDict["seq"] = relate
    ptlist = [mc.xform(newDict[rel],q=True,ws=True,t=True) for rel in relate]
    cvnum = len(ptlist)
    if cvnum > 2:
        deg = 2
    else:
        deg = 1
    
    mc.delete(sdict[sc.sCrv])
    crv = mc.curve(name=con.lname(prefix, star, sc.sCrv + bc.gTemplate),
                   p=ptlist, d=deg, ws=True)
    newDict[sc.sCrv] = crv
    if number != 3:
        
        mc.rebuildCurve(sdict[sc.sCrv],s=number-1,d=1,tol=0.01,)
    data = json.dumps(newDict)
    mc.setAttr("{}.{}".format(localPrefix,"crvData"),data,type="string")
    
    crvShape = con.findRelatedShape(crv)
    for i,k in enumerate(relate):
        tshape = con.findRelatedShape(newDict[k])
        mc.connectAttr(tshape+".wp[0]",crvShape+".cp[%s]"%i)
        
    mc.parent(crv,bc.gBodyTemplate)
    mc.joint(tjotlist, e=True, oj='yzx', secondaryAxisOrient='zup', ch=True, zso=True)
    mc.setAttr('%s.jointOrient' % (tjotlist[-1]), 0, 0, 0)

    return newDict

def importBodyTemplate():
    
    sd = importSpineTemplate("",tag=bc.gSpine)
    nd = importSpineTemplate("",tag=bc.gNeck)
    ad = importArmTemplate("")
    ld = importLegTemplate("")
    initpt = [12,18,1]
    
    for i,k in enumerate([bc.gThumb, bc.gIndex, bc.gMiddle, bc.gRing, bc.gPinky]):
        
        fd = importFingerTemplate("",tag=k,saxial=i*0.5,initpt=initpt)
        # mc.parent(fd[sc.sGrp], ad[bc.gHand])

    # mc.parent(ad[sc.sGrp],nd[sc.sGrp],sd[bc.gChest])
    # mc.parent(ld[sc.sGrp],sd[bc.gSpine])
    
    return
def importFingerTemplate(prefix="def",tag=bc.gIndex,axial='x',saxial=0,initpt=(0,0,0)):
    localGrp, localSet = localInit(tag+bc.gFinger, prefix)
    
    newDict = {sc.sGrp: localGrp, "make": prefix}
    pat = None
    tloclist = list()
    relate = ["%s%s"%(tag,_) for _ in range(1,6,1)]
    newDict["seq"] = relate
    ix,iy,iz = initpt
    for i,rel in enumerate(relate):
        
        if axial == 'x':
            pt = (i+ix,iy,iz-saxial)
        elif axial == 'y':
            pt = (ix,i+iy,iz-saxial)
        elif axial == 'z':
            pt = (ix-saxial,iy,i+iz)
        tloc = tempLoc("_".join([prefix, rel]), pt)
        mc.setAttr(tloc+".radius",0.5)

        tGrp = con.emptyGroup(tloc, ["Zero"])
        if pat is not None:
            mc.parent(tGrp[0], pat)
        else:
            mc.parent(tGrp[0], localGrp)
        pat = tloc
        newDict[rel] = tloc
        mc.sets(tloc, add=localSet)
        con.lockHideAttr(tloc, ["sx", "sy", "sz", "v"])
        tloclist.append(tloc)
        
    mc.joint(tloclist, e=True, oj='yzx', secondaryAxisOrient='zup', ch=True, zso=True)
    data = json.dumps(newDict)
    
    con.addStringAttr(localSet, "crvData", data)
    
    return newDict

if __name__ == '__main__':
    pass